package com.example.pos_terminal;

import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
import android.util.Log;
import android.webkit.JavascriptInterface;

import com.decard.NDKMethod.BasicOper;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import config.CommonValue;
import tools.HexToString;
import tools.MD5Util;
import tools.StringUtils;
import tools.SystemUtil;
import tools.TimeTools;

import static com.example.pos_terminal.MainActivity.isPaying;
import static tools.Finals.deka_product_model;
import static tools.Finals.shangmi_product_model;

public class pay {

    private static final String TAG = "";
    private ScheduledExecutorService executorService;
    private String cardNumber = "";
    private String scan2Dinfo = "";
    private String result = "";
    private X5WebView webView;
    private MainActivity mainActivity;
    private boolean flag = true;
    public static Context context;
    public SoundPool soundPool = null;

    public pay(X5WebView webView, MainActivity mainActivity, Context context) {
        this.webView = webView;
        this.mainActivity = mainActivity;
        this.context = context;
        soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
        soundPool.load(context, R.raw.di, 1);
    }

    String macAddress;

    @JavascriptInterface
    public void getpay() {
        BasicOper.dc_Scan2DBarcodeStart(0x00);
        BasicOper.dc_load_key_hex(0, 1, "FFFFFFFFFFFF");
        if (deka_product_model.equals(SystemUtil.getSystemModel())) {
            if (executorService==null || executorService.isShutdown()){
                executorService = Executors.newScheduledThreadPool(1);
                executorService.scheduleAtFixedRate(this::getpay1, 0, 200, TimeUnit.MILLISECONDS);
            }
        } else if (shangmi_product_model.equals(SystemUtil.getSystemModel())) {
            mainActivity.registerReceiver(mainActivity.getReceiver(), mainActivity.getFilter());
            isPaying = true;
        }

    }

    @JavascriptInterface
    public void getpayFlow() {
        BasicOper.dc_Scan2DBarcodeStart(0x00);
        if (deka_product_model.equals(SystemUtil.getSystemModel())) {
            if (executorService==null || executorService.isShutdown()){
                executorService = Executors.newScheduledThreadPool(1);
                executorService.scheduleAtFixedRate(this::getpayFlow1, 0, 200, TimeUnit.MILLISECONDS);
            }
        } else if (shangmi_product_model.equals(SystemUtil.getSystemModel())) {
            mainActivity.registerReceiver(mainActivity.getReceiver(), mainActivity.getFilter());
            isPaying = true;
        }

    }

    @JavascriptInterface
    public void close() {
        if (deka_product_model.equals(SystemUtil.getSystemModel())) {
            executorService.shutdownNow();
            flag = false;
        } else if (shangmi_product_model.equals(SystemUtil.getSystemModel())) {
            mainActivity.unregisterReceiver(mainActivity.getReceiver());
            isPaying = false;
        }
    }


    @JavascriptInterface
    public void getpay1() {
        String scan_2D_info = BasicOper.dc_Scan2DBarcodeGetData();
        String card_number = "";
        if (StringUtils.notEmpty(scan_2D_info) && !scan_2D_info.equals("FFFF|未知错误")) {
            soundPool.play(1, 1, 1, 10, 0, 1);
            scan_2D_info = scan_2D_info.replace("0000|", "");
            String finalScan_2D_info1 = HexToString.decode(scan_2D_info);
            if (finalScan_2D_info1.contains("&")) {
                //虚拟卡账户支付
                card(finalScan_2D_info1);
            } else if (CommonValue.openPay) {
                webView.post(() -> webView.evaluateJavascript("javascript:fn('" + finalScan_2D_info1 + "')", (val) -> { }));
                executorService.shutdownNow();
            }
        } else {
            card_number = read_M1_card(1, 0, 0, 0);
            if (StringUtils.notEmpty(card_number)) {
                soundPool.play(1, 1, 1, 10, 0, 1);
                String finalCard_number = "javascript:fn(" + card_number + ")";
                webView.post(() -> webView.loadUrl(finalCard_number));
                executorService.shutdownNow();
            }

        }
    }


    @JavascriptInterface
    public void getpayFlow1() {
        String scan_2D_info = BasicOper.dc_Scan2DBarcodeGetData().replace("0000|", "");
        if (StringUtils.notEmpty(scan_2D_info) && !scan_2D_info.equals("FFFF|未知错误")) {
            soundPool.play(1, 1, 1, 10, 0, 1);
            String finalScan_2D_info1 = HexToString.decode(scan_2D_info);
            webView.post(() -> webView.evaluateJavascript("javascript:flow('" + finalScan_2D_info1 + "')", (val) -> { }));
            executorService.shutdownNow();
        }
    }

    public ExecutorService getExecutorService() {
        return executorService;
    }

    /**
     * @param card_n_hex 操作类型
     *                   0x00:对空闲卡进行操作  0x01对所有卡进行操作
     * @param model      密码类型
     *                   0x00 - 表示用设备内部装载的第0套A密码来验证当前选取卡片的A密码。
     *                   0x01 - 表示用设备内部装载的第1套A密码来验证当前选取卡片的A密码。
     *                   0x02 - 表示用设备内部装载的第2套A密码来验证当前选取卡片的A密码。
     *                   0x04 - 表示用设备内部装载的第0套B密码来验证当前选取卡片的B密码。
     *                   0x05 - 表示用设备内部装载的第1套B密码来验证当前选取卡片的B密码。
     *                   0x06 - 表示用设备内部装载的第2套B密码来验证当前选取卡片的B密码。
     * @param secNum     对应装载的扇区号 0-15
     * @param key        秘钥
     * @param index      读取的块地址号
     * @brief 装载秘钥
     */

    @JavascriptInterface
    public String load_M1_key(int card_n_hex, int model, int secNum, String key, int index) {
        String load_key_hex = BasicOper.dc_load_key_hex(model, secNum, key).split("\\|")[0]; //装载设备密码
        if (load_key_hex.equals("0000")) {
            long timeOut = System.currentTimeMillis();//获取系统当前时间
            String card_number = "";
            while (load_key_hex.equals("0000")) {
                card_number = read_M1_card(card_n_hex, model, secNum, index);
                if (!card_number.equals("")) {
                    break;
                }
                if (System.currentTimeMillis() - timeOut > 20000) {           //扫描超时时退出扫描
                    break;
                }
            }
            Log.d(TAG, "BasicOper.dc_load_key_hex: 设备密码装载成功！");
            return card_number;
        } else Log.d(TAG, "BasicOper.dc_load_key_hex: 设备密码装载失败！");
        return "";
    }


    public String getCardId(String load_key_hex) {
        long timeOut = System.currentTimeMillis();//获取系统当前时间
        String card_number = "";
        while (load_key_hex.equals("0000")) {
            card_number = read_M1_card(1, 4, 0, 0);
            if (!card_number.equals("")) {
                break;
            }
            if (System.currentTimeMillis() - timeOut > 100000) {           //扫描超时时退出扫描
                break;
            }
        }
        return card_number;
    }

    /**
     * @param card_n_hex 操作类型
     *                   0x00:对空闲卡进行操作  0x01对所有卡进行操作
     * @param model      密码类型
     *                   0x00 - 表示用设备内部装载的第0套A密码来验证当前选取卡片的A密码。
     *                   0x01 - 表示用设备内部装载的第1套A密码来验证当前选取卡片的A密码。
     *                   0x02 - 表示用设备内部装载的第2套A密码来验证当前选取卡片的A密码。
     *                   0x04 - 表示用设备内部装载的第0套B密码来验证当前选取卡片的B密码。
     *                   0x05 - 表示用设备内部装载的第1套B密码来验证当前选取卡片的B密码。
     *                   0x06 - 表示用设备内部装载的第2套B密码来验证当前选取卡片的B密码。
     * @param secNum     对应验证的扇区号
     * @param index      读取的块地址号
     * @brief 读取M1卡信息
     */
    private static String read_M1_card(int card_n_hex, int model, int secNum, int index) {
        String config_card = BasicOper.dc_config_card(0).split("\\|")[0];
        if (config_card.equals("0000")) {
            String temp_card_n_hex_str = BasicOper.dc_card_n_hex(card_n_hex);      //寻卡、防冲突、选卡    param：0x00:对空闲卡进行操作  0x01对所有卡进行操作
            Log.d(TAG, "BasicOper.dc_card_n_hex_str: 寻卡状态！" + temp_card_n_hex_str);
            String temp_card_n_hex = temp_card_n_hex_str.split("\\|")[0];
            Log.d(TAG, "BasicOper.dc_card_n_hex: 寻卡状态！" + temp_card_n_hex);
            if (temp_card_n_hex.equals("0000")) {
                String authentication_pass = BasicOper.dc_authentication(model, secNum).split("\\|")[0];
                Log.d(TAG, "BasicOper.dc_authentication: 秘钥验证返回值！" + authentication_pass);
                if (authentication_pass.equals("0000")) {
                    Log.d(TAG, "BasicOper.dc_authentication_pass: 密钥验证成功！");
                    String card_info = BasicOper.dc_read_hex(index);
                    card_info = card_info.split("\\|")[1];
                    String cardId = "";
                    System.out.println(card_info);
                    if (card_info.equals("未知错误")) {
                        return "";
                    }
                    card_info = card_info.substring(0, 8);
                    for (int i = card_info.length(); i > 1; i -= 2) {
                        cardId += card_info.substring(i - 2, i);
                        ;
                    }
                    Log.d(TAG, "BasicOper.dc_read_hex：" + String.valueOf(Long.parseLong(cardId, 16)));
                    return String.valueOf(Long.parseLong(cardId, 16));//读取数据  param: index:块号

                }
            } else {
                String authentication = BasicOper.dc_authentication(4, secNum).split("\\|")[0];
                if (authentication.equals("0000")) {
                    Log.d(TAG, "BasicOper.dc_authentication_pass: 密钥验证成功！");
                    String card_infonew = BasicOper.dc_read_hex(index);
                    card_infonew = card_infonew.split("\\|")[1];
                    String cardIdnew = "";
                    System.out.println(card_infonew);
                    if (card_infonew.equals("未知错误")) {
                        return "";
                    }
                    card_infonew = card_infonew.substring(0, 8);
                    for (int i = card_infonew.length(); i > 1; i -= 2) {
                        cardIdnew += card_infonew.substring(i - 2, i);
                        ;
                    }
                    Log.d(TAG, "BasicOper.dc_read_hex：" + String.valueOf(Long.parseLong(cardIdnew, 16)));
                    return String.valueOf(Long.parseLong(cardIdnew, 16));//读取数据  param: index:块号

                }
            }
        }
        return "";
    }

    /**
     * @param card_n_hex 操作类型
     *                   0x00:对空闲卡进行操作  0x01对所有卡进行操作
     * @param model      密码类型
     *                   0x00 - 表示用设备内部装载的第0套A密码来验证当前选取卡片的A密码。
     *                   0x01 - 表示用设备内部装载的第1套A密码来验证当前选取卡片的A密码。
     *                   0x02 - 表示用设备内部装载的第2套A密码来验证当前选取卡片的A密码。
     *                   0x04 - 表示用设备内部装载的第0套B密码来验证当前选取卡片的B密码。
     *                   0x05 - 表示用设备内部装载的第1套B密码来验证当前选取卡片的B密码。
     *                   0x06 - 表示用设备内部装载的第2套B密码来验证当前选取卡片的B密码。
     * @param secNum     对应验证的扇区号
     * @param index      写入的块地址号
     * @brief M1卡信息写入
     */
    public static void write_M1_card(int card_n_hex, int model, int secNum, int index) {
        String temp_card_n_hex = BasicOper.dc_card_n_hex(card_n_hex).split("\\|")[0];      //寻卡、防冲突、选卡    param：0x00:对空闲卡进行操作  0x01对所有卡进行操作
        if (temp_card_n_hex.equals("0000")) {
            Log.d(TAG, "BasicOper.dc_card_n_hex: 寻卡成功！");
            String authentication_pass = BasicOper.dc_authentication_pass(model, secNum, "FFFFFFFFFFFF").split("\\|")[0];
            if (authentication_pass.equals("0000")) {
                Log.d(TAG, "BasicOper.dc_authentication_pass: 密钥验证成功！");
                String card_info = BasicOper.dc_write_hex(index, "00000000000000000000000000000001");
                Log.d(TAG, "BasicOper.dc_write_hex：" + card_info);
            }
        }
    }


    @JavascriptInterface
    public String getMacAddress() {
        return macAddress;
    }

    public void setMacAddress(String macAddress) {
        this.macAddress = macAddress;
    }


    public void card(String scan_2D_info) {
        String[] split = scan_2D_info.split("&");
        if (split.length < 4) {
            webView.post(() -> webView.loadUrl("javascript:fn(" + "" + ")"));
            String finalCard_number = "javascript:fn(" + "" + ")";
            webView.post(() -> webView.loadUrl(finalCard_number));
            return;
        }
        final String time = split[1];
        final String substring = split[2];
        final String paySign = split[0];
        final String idNumber = split[3];
        DateFormat dtf = new SimpleDateFormat("yyMMddHHmmss");
        Calendar oldTime = null;
        try {
            oldTime = TimeTools.string2Calendar(time, dtf);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        oldTime.add(Calendar.MINUTE, 5);
        if (oldTime.after(Calendar.getInstance())) {
            //检验签名
            String str = idNumber + substring + time;
            String sign = MD5Util.getMD5String(str).toUpperCase();
            if (sign.equals(paySign)) {
                //签名验证通过
                String finalCard_number = "javascript:fn('&" + idNumber + "')";
                webView.post(() -> webView.loadUrl(finalCard_number));
                executorService.shutdownNow();
            } else {
//                        String finalCard_number = "javascript:fn()";
                webView.post(() -> webView.loadUrl("javascript:fn()"));
            }
//
        } else {
            webView.post(() -> webView.loadUrl("javascript:fn()"));
//            getpay();
        }
    }
}
